(defun half (n)
  (floor (/ n 2)))

(defun list-divisors (n)
  (loop for i from 1 to (sqrt n)
     when (= (mod n i) 0)
     collect i
     and unless (= i (/ n i))
     collect (/ n i)))

(defun list-divisors-slow (n)
  (let ((fact nil))
    (dotimes (i (half n) fact)
      (if (zerop (mod n (1+ i))) 
	  (setq fact (cons (1+ i) fact))))))

(defun sum-divisors (n)
  (reduce #'+ (remove n (list-divisors n))))

(defun abundantp (n)
  (> (sum-divisors n) n))

(defun list-abundants (max)
  (let ((a (make-array max :fill-pointer 0)))
    (loop for i from 1 to max
       when (abundantp i)
       do (vector-push i a) 
       finally (return a))))

(defun list-all-numbers(max)
  (loop for i from 1 to max
	collect i))

(defun probl23(max)
  (let ((all-numbers (list-all-numbers max))
	(abundants (list-abundants max)))
    (loop for i from 0 to (1- (length abundants)) do
	 (loop for j from 0 to i
	      for s = (+ (elt abundants i) (elt abundants j))
	    ;when (< (+ (nth i abundants) (nth j abundants)) max)
	      do (if (> s max) 
		     (return)
	    ;;do (setq all-numbers (cons (+ (nth i abundants) (nth j abundants)) all-numbers)))
	     ; do (delete (+ (nth i abundants) (nth j abundants)) all-numbers))
		     (delete s all-numbers)))
	    finally (return  (reduce #'+ all-numbers)))))
       ;finally (return all-numbers))))

(defun generate-abundants(max)
  (let ((abundants-sum ())
	(abundants (list-abundants max)))
    (loop for i from 0 to (1- (length abundants)) do
	 (loop for j from 0 to i 
	    when (< (+ (nth i abundants) (nth j abundants)) max)
	    do; (if (not (find (+ (nth i abundants) (nth j abundants)) abundants-sum)) 
		   (setq abundants-sum (cons (+ (nth i abundants) (nth j abundants)) abundants-sum)))
       finally (return  abundants-sum))))

(defun probl23-2 ( max )
  (let ((abundants-sum (generate-abundants max)))
    (loop for i from 1 to max when (not (find i abundants-sum))
	 sum i)))
